iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 23
1

之前在service worker中寫了這麼多cache strategiesbackground sync等等的程式碼,但是隨著我們開發的專案越來越大、檔案越來越多,管理service worker的工作也就越來越複雜。難道沒有什麼方便的工具能讓我們「自動化管理service worker」嗎?

/images/emoticon/emoticon02.gif 有der~~那就是Google提供的 workbox tool

由於大多數網站都包含html、css、javascript和圖像,這裡我們可以透過Workbox來使用「一些通用策略」對網頁資源進行暫存。

那要怎麼使用workbox呢?首先,先來安裝它的command line套件吧(使用2.0.0版本):

npm install --save-dev workbox-cli@^2.0.0

另外,在package.json中添加npm執行workbox的腳本:

"scripts": {
    "start": "http-server -c-1",
    "generate-sw": "workbox generate:sw"
}

接著在command line中執行npm run generate-sw

畫面會出現一連串的要求設定:

  • 首先將我們project的跟目錄設為public
  • 接著選擇那些檔案類型要暫存到cache中(這裡預設全選)
  • 最後新增service worker file(這裡為了避免覆蓋掉原本的sw.js所以我命名為service-worker.js)。

workbox會在專案目錄下產生4個file:

+-- public
|   +-- service-worker.js
|   +-- workbox-sw.prod.v2.1.3.js
|   +-- workbox-sw.prod.v2.1.3.js.map
+-- workbox-cli-config.js

其中在service-worker.js可以發現「fileManifest陣列」中已經設置了非常多準備要cache的檔案,每個file會有一個revisoion,可以把它想成是更新版本號。當這些檔案更新時,再次執行npm run generate-sw,版本號也會隨之更新:

fileManifest = [
  {
    "url": "404.html",
    "revision": "0a27a4163254fc8fce870c8cc3a3f94f"
  },
  {
    "url": "favicon.ico",
    "revision": "2cab47d9e04d664d93c8d91aec59e812"
  },
  {
    "url": "index.html",
    "revision": "9aaca300f5d996d0d8f4dbbbc8d2f72c"
  },
  {
    "url": "manifest.json",
    "revision": "1fa5aa1aade821474e2063a7521870f2"
  },
  {
    "url": "offline.html",
    "revision": "6bca1d9bf0f30b72fcac1826ca248b2b"
  },
  ... 以下省略 ...
]

const workboxSW = new self.WorkboxSW();
workboxSW.precache(fileManifest);

最後兩行為建立一個workbox service worker實例,並透過precache方法,將上述要暫存的檔案傳入。

在看新的service worker是否能正常運行前,記得在app.js中將註冊service worker從「sw.js」改成「service-worker.js」。

可以發現Cache Storage中已經新增了一個「workbox-precaching」的sub cache:

如果是在離線狀態下呢?

Nooooo!! 雖然已經precache一些靜態檔案了,不過像是material design CDN或是google fonts的圖示都沒有被暫存到。

所以接下來就要來看看要怎麼針對這些「特定的外部url資源」採取「特定的cache strategies」(這些其實在我們舊的sw.js中都已經實作出來了)。


在處理上述的問題前,我在這裡並不想要precacahe icons以及help folder。所以必須對workbox-cli-config.js中的「globPatterns」和「globIgnores」屬性進行修改,前者是去定義我們要precache的檔案路徑和類型,後者為要省略的檔案。

"globPatterns": [
    "**/*.{html,ico,json,css,js}",
    "src/images/*.{jpg,png}"   // 這裡我只想要precache src/images路徑下的圖像並不包含icons資料夾
]
"globIgnores": [
    "../workbox-cli-config.js",
    "help/**"   // 將help資料夾下所有的file省略,不進行暫存
]

記得要重新執行 npm run generate-sw


接續剛剛要處理的問題,針對「特定的外部url資源」採取「特定的cache strategies」要怎麼透過workbox來實作呢?這裡就要開始使用workbox中的routing功能。

首先,我現在每次執行npm run generate-sw指令時,都會重新產生並覆蓋原有的service-worker.js檔案,這樣其實非常沒有效率。

這裡有一個更好的方式,我們只希望更新「要precache的fileManifest陣列」。所以在這邊我新增一個sw-base.js檔案,並在裡面添加:

importScripts('workbox-sw.prod.v2.1.3.js');

const workboxSW = new self.WorkboxSW();
workboxSW.precache([]);   // 我用一個空陣列來取代原有的fileManifest陣列

然後在workbox-cli-config.js中將sw-base.js添加到「swSrc」這個屬性中:

"swSrc": "public/sw-base.js"

接著在package.json中,將原本執行的workbox腳本從「workbox generate:sw」更改為「workbox inject:manifest」。

而這個inject:manifest指令就是讓我們每次執行時,不用再產生全新的service-worker.js file,而是先到config file中的swSrc屬性了解到要以sw-base.js為基礎,並將「更新後的fileManifest陣列」注入到空陣列中,最後把整個結果寫入到service-worker.js檔案中。

接下來終於要在service-worker.js中,加入我們的routing邏輯了(這裡是要針對外部的google fonts CDN):

workboxSW.router.registerRoute(/.*(?:googleapis|gstatic)\.com.*$/, workboxSW.strategies.staleWhileRevalidate({
    cacheName: 'google-fonts'
}));

感覺只有短短的幾行,其實workbox幫我們做了非常多的工作。首先,router.registerRoute()這個方法接受2個參數,第一個為我們要routing的url(可以用正規表達式),第二個為我們要使用的cache strategies。

所以這裡在第一個參數中我將要路由的網址設定為包含了googleapis.comgstatic.com第二個參數透過strategies這個屬性將所要的cache strategies指定為「staleWhileRevalidate()」。

staleWhileRevalidate其實就是之前實作過的「cache then network strategies」,這裡就不多說明XD

而在staleWhileRevalidate()這個method中可以輸入一個javascript object,裡面可以設定的屬性非常多,這裡我只將上述的google fonts外部資源暫存到「google-fonts」這個sub cache中。

Day28 結束!! /images/emoticon/emoticon37.gif


上一篇
[Day27] 了解Media API和Geolocation API(Part3)
下一篇
[Day29] 自動化管理Service Worker(Part2)
系列文
你應該要知道的新一代Web技術---漸進式網頁(PWA)29
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言